package finance

import (
	"context"
	"engine/consts"
	"engine/dto"
	emodel "engine/model"
	"fmt"
	"github.com/SebastiaanKlippert/go-wkhtmltopdf"
	"github.com/xuri/excelize/v2"
	"golang.org/x/text/language"
	"golang.org/x/text/message"
	"lib/aliyun"
	"lib/emails"
	"lib/log"
	"strconv"
	"strings"
	"time"
)

func AgencyBill() {
	agencyList, err := dto.GetActiveAgencyAll()
	if err != nil {
		log.Errorf("AgencyBill GetActiveAgency err: %v", err)
		return
	}
	newTime := time.Now().Unix()

	for _, agencyInfo := range agencyList {
		if agencyInfo.Config == nil {
			log.Errorf("供应商[%s]配置不正确", agencyInfo.Name)
			continue
		}
		StatementsBillType := agencyInfo.Config.CommonConfig.StatementsBillType
		if StatementsBillType != "" {
			taskNum := agencyInfo.Config.CommonConfig.StatementsBillNum
			if taskNum <= 0 {
				sysErr := emodel.SysError{
					ErrorCode: fmt.Sprintf("AgencyBill"),
					Msg:       fmt.Sprintf("%v%d", "taskNum err --", taskNum),
				}
				err = dto.Create(&sysErr)
				if err != nil {
					log.Errorf("AgencyBill dto.Create(sysErr) err: %v", err)
				}
				continue
			}
			switch StatementsBillType {
			case "天":
				if newTime > (agencyInfo.BillTime + (int64(taskNum)*86400 - 10)) {
					startDay := time.Now().AddDate(0, 0, -taskNum)
					endDay := time.Now().AddDate(0, 0, -1)
					createExcel(agencyInfo, newTime, &startDay, &endDay)
				}
			case "周":
				if newTime > agencyInfo.BillTime+(86400*(7*int64(taskNum))-10) {
					startDay := time.Now().AddDate(0, 0, -(7*taskNum + 1))
					endDay := time.Now().AddDate(0, 0, -1)
					createExcel(agencyInfo, newTime, &startDay, &endDay)
				}
			case "月":
				if newTime > agencyInfo.BillTime+(86400*(30*int64(taskNum))-10) {
					startDay := time.Now().AddDate(0, -(taskNum), -1)
					endDay := time.Now().AddDate(0, 0, -1)
					createExcel(agencyInfo, newTime, &startDay, &endDay)
				}
			}
		}
	}
}

func createExcel(agencyInfo *emodel.Agency, newBillTime int64, startDay, endDay *time.Time) {
	agencyBills, err := dto.GetAgencyBalanceChange(agencyInfo.Id, startDay, endDay)
	if err != nil {
		log.Errorf("查询代理商账单失败：%v", err)
		return
	}

	agencyInfo.BillTime = newBillTime
	err = dto.UpdateAgencyBillTime(context.Background(), agencyInfo)
	if err != nil {
		log.Errorf("AgencyBill dto.Update(sysErr) err: %v", err)
		return
	}

	if len(agencyBills) > 0 {
		go func() {
			defer func() {
				err := recover()
				if err != nil {
					log.Errorf("BillExcel error: %v", err)
				}
			}()

			err := BillExcel(agencyBills, agencyInfo.Id, startDay, endDay)
			if err != nil {
				log.Errorf("BillExcel error: %v", err)
			}
		}()
	}
}

func BillExcel(agencyBill []*emodel.AgencyBalanceChange, agencyId uint64, startDay *time.Time, endDay *time.Time) error {

	return nil
}

func uploadFileToOss(filePath string) (newFilePath string, err error) {
	fullPath := strings.Split(filePath, "/")
	oss := aliyun.OssService{
		IsPrivate: true,
	}
	ossFilePath := ""
	for i := 0; i < len(fullPath); i++ {
		if i < 2 {
			continue
		}
		ossFilePath += "/" + fullPath[i]
	}
	newFilePath, err = oss.UploadFileLocation(filePath, ossFilePath[1:], false)
	if err != nil {
		log.Errorf("%v", err)
		return "", err
	}
	//oss.GetFileUrl(newFilePath)
	return newFilePath, err
}

func createPdf(agency map[string]interface{}, agencyBill []emodel.AgencyBillsPdfData, newPath string) error {
	pdfg, err := wkhtmltopdf.NewPDFGenerator()
	if err != nil {
		log.Errorf("新建pdf文件对象失败：%v", err)
		return err
	}

	newData := struct {
		AgencyBill []emodel.AgencyBillsPdfData
		Agency     map[string]interface{}
	}{agencyBill, agency}

	htmlStr := emails.RenderTemplate("resources/templates/agencystatement.blade.html", newData)
	page := wkhtmltopdf.NewPageReader(strings.NewReader(htmlStr))

	page.HeaderFontSize.Set(9)
	page.HeaderRight.Set(" [page] / [toPage]  ")
	page.HeaderSpacing.Set(10)

	pdfg.AddPage(page)

	err = pdfg.Create()
	if err != nil {
		log.Errorf("createPdf dfg.Create() err:%s", err.Error())
		return err
	}
	//Your Pdf Name
	err = pdfg.WriteFile(newPath + "-statement.pdf")
	if err != nil {
		log.Errorf("createPdf pdfg.WriteFile(newPath + \"-statement.pdf\") err:%s", err.Error())
		return err
	}
	return nil
}

func setCells(f *excelize.File, financialItem *emodel.FinancialList, index int) error {
	ticketNos := func(OrderTickets []*emodel.OrderTicket) (ticketNos string) {
		for ticketKey, ticket := range OrderTickets {
			ticketNos += ticket.TicketNo
			if ticketKey > 0 {
				ticketNos += "\n"
			}
		}
		return
	}
	orderTypeMap := map[consts.FlightOrderType]string{
		consts.FlightOrderTypeOrigin: "原单",
		consts.FlightOrderTypeRefund: "退票单",
		consts.FlightOrderTypeVoid:   "废票单",
		consts.FlightOrderTypeChange: "改期单",
	}
	channelMp := map[consts.SysIncomeChannel]string{
		consts.SysIncomeChannelBalance:       "余额",
		consts.SysIncomeChannelAlipay:        "支付宝",
		consts.SysIncomeChannelWeChatPay:     "微信",
		consts.SysIncomeChannelYeeAlipay:     "易宝-支付宝",
		consts.SysIncomeChannelYeeWeChatPay:  "易宝-微信",
		consts.SysIncomeChannelYeeCreditCard: "易宝-信用卡",
		consts.SysIncomeChannelYeeDebitCard:  "易宝-借记卡",
	}
	orderStatus := map[consts.FlightOrderStatus]string{
		consts.FlightOrderStatusReviewing:           "待审核",
		consts.FlightOrderStatusToBePaid:            "待支付",
		consts.FlightOrderStatusReserved:            "已留座",
		consts.FlightOrderStatusProceeding:          "出票中",
		consts.FlightOrderStatusIssued:              "已出票",
		consts.FlightOrderStatusFailed:              "预定失败",
		consts.FlightOrderStatusFailedReimbursing:   "预订失败，退款中",
		consts.FlightOrderStatusFailedReimbursed:    "预订失败，已退款",
		consts.FlightOrderStatusChgReviewing:        "改期待审核",
		consts.FlightOrderStatusChgToBePaid:         "改期待支付",
		consts.FlightOrderStatusChgProceeding:       "改期中",
		consts.FlightOrderStatusChanged:             "改期已出票",
		consts.FlightOrderStatusRfdReviewing:        "退票待审核",
		consts.FlightOrderStatusRfdToBeConfirm:      "退票待确认",
		consts.FlightOrderStatusRfdProceeding:       "退票中",
		consts.FlightOrderStatusRefundedReimbursing: "已退票，待退款",
		consts.FlightOrderStatusRefundedReimbursed:  "已退票，已退款",
		consts.FlightOrderStatusVoidProceeding:      "废票中",
		consts.FlightOrderStatusVoidedReimbursing:   "已废票待退款",
		consts.FlightOrderStatusVoidedReimbursed:    "已废票已退款",
		consts.FlightOrderStatusClosed:              "订单关闭",
		consts.FlightOrderStatusCanceled:            "订单取消",
	}
	if err := f.SetCellValue("Sheet1", "A"+strconv.Itoa(index), orderTypeMap[financialItem.OrderType]); err != nil {
		return err
	}
	if err := f.SetCellValue("Sheet1", "B"+strconv.Itoa(index), financialItem.OrderNo); err != nil {
		return err
	}
	if err := f.SetCellValue("Sheet1", "C"+strconv.Itoa(index), orderStatus[financialItem.Status]); err != nil {
		return err
	}
	if err := f.SetCellValue("Sheet1", "D"+strconv.Itoa(index), financialItem.ThirdOrderId); err != nil {
		return err
	}
	if err := f.SetCellValue("Sheet1", "E"+strconv.Itoa(index), financialItem.Agency); err != nil {
		return err
	}
	if err := f.SetCellFloat("Sheet1", "F"+strconv.Itoa(index), financialItem.AgencyAmount.InexactFloat64(), -1, 64); err != nil {
		return err
	}
	if err := f.SetCellValue("Sheet1", "G"+strconv.Itoa(index), channelMp[financialItem.AgencyChannel]); err != nil {
		return err
	}
	if err := f.SetCellFloat("Sheet1", "H"+strconv.Itoa(index), financialItem.AgencyTransactionFee.InexactFloat64(), -1, 64); err != nil {
		return err
	}
	if err := f.SetCellFloat("Sheet1", "I"+strconv.Itoa(index), financialItem.AgencyPaidAmount.InexactFloat64(), -1, 64); err != nil {
		return err
	}
	if err := f.SetCellValue("Sheet1", "J"+strconv.Itoa(index), financialItem.ThirdCode); err != nil {
		return err
	}
	if err := f.SetCellFloat("Sheet1", "K"+strconv.Itoa(index), financialItem.ThirdCost.InexactFloat64(), -1, 64); err != nil {
		return err
	}
	if err := f.SetCellFloat("Sheet1", "L"+strconv.Itoa(index), (financialItem.AgencyAmount.Sub(financialItem.ThirdCost)).InexactFloat64(), -1, 64); err != nil {
		return err
	}
	if err := f.SetCellValue("Sheet1", "M"+strconv.Itoa(index), financialItem.SaleName); err != nil {
		return err
	}
	if err := f.SetCellValue("Sheet1", "N"+strconv.Itoa(index), ticketNos(financialItem.OrderTickets)); err != nil {
		return err
	}
	if err := f.SetCellInt("Sheet1", "O"+strconv.Itoa(index), len(financialItem.OrderTickets)); err != nil {
		return err
	}
	if err := f.SetCellValue("Sheet1", "P"+strconv.Itoa(index), financialItem.CompletedAt); err != nil {
		return err
	}
	if err := f.SetCellValue("Sheet1", "Q"+strconv.Itoa(index), financialItem.OrderCreatedAt); err != nil {
		return err
	}
	return nil
}

func formatNumberWithCommas(value float64) string {
	p := message.NewPrinter(language.English)
	return p.Sprintf("%.2f", value)
}
